import logging

from poker_bot.core.models.dto import UserDTO
from poker_bot.core.models.dto.deposit import DepositDTO, DepositWithDetailsDTO
from poker_bot.core.models.enums.deposit import DepositStatus
from poker_bot.database.uow import SQLAlchemyUoW
from poker_bot.domain.deposit import DepositEntity

logger = logging.getLogger(__name__)


class DepositService:
    def __init__(self, uow: SQLAlchemyUoW):
        self._uow = uow

    async def get_deposit_by_id(self, deposit_id: int) -> DepositWithDetailsDTO:
        """Получаем депозит по id"""

        return await self._uow.deposit_reader.get_deposit_by_id(deposit_id)

    async def get_all_deposits(self) -> list[DepositWithDetailsDTO]:
        return await self._uow.deposit_reader.get_all_deposits()

    async def get_user_deposits(self, user_tg_id: int) -> list[DepositDTO]:
        """Получаем заказы пользователя"""

        return await self._uow.deposit_reader.get_user_deposits(user_tg_id)

    async def get_deposits_for_confirmation(
        self,
    ) -> list[DepositWithDetailsDTO]:
        """Получаем депозиты с неподтвержденной оплатой"""

        return await self._uow.deposit_reader.get_deposits_for_confirmation()

    async def create_deposit(
        self, summ: float, user_tg_id: int, payment_method_id: int, account_id: int
    ) -> DepositEntity:
        """
        Создаем депозит
        @param summ: Сумма депозита
        @param user_tg_id: Telegram id пользователя
        @param payment_method_id: Id метода оплаты
        @param account_id: Id аккаунта
        @return:
        """

        user: UserDTO = await self._uow.user_reader.get_user_by_tg_id(user_tg_id)
        deposit = DepositEntity.create(
            summ=summ,
            buyer_db_id=user.id,
            payment_method_id=payment_method_id,
            account_id=account_id,
        )
        try:
            deposit = await self._uow.deposit_repo.create_deposit(deposit)
        except Exception as err:
            await self._uow.rollback()
            raise err

        await self._uow.commit()

        logger.info(f"Deposit was created: {deposit.id}")

        return deposit

    async def update_deposit_status(
        self, deposit_id: int, deposit_status: DepositStatus
    ) -> None:
        """Обновляем статус заказа"""

        deposit: DepositEntity = await self._uow.deposit_repo.acquire_deposit_by_id(
            deposit_id
        )
        deposit.update_status(deposit_status)

        await self._uow.deposit_repo.update_deposit(deposit)

        await self._uow.commit()

        logger.info(
            f"Deposit {deposit_id} status was updated. New status: {deposit_status}"
        )

    async def update_deposit_payment_method(
        self, deposit_id: int, payment_method_id: int
    ) -> None:
        """Обновляем метод оплаты депозита"""

        deposit: DepositEntity = await self._uow.deposit_repo.acquire_deposit_by_id(
            deposit_id
        )
        deposit.update_status(DepositStatus.waiting_payment)
        deposit.update_payment_method(payment_method_id)

        await self._uow.deposit_repo.update_deposit(deposit)

        await self._uow.commit()

    async def update_deposit_invoice_path(
        self, deposit_id: int, invoice_filename: str
    ) -> None:
        """Обновляем путь к скриншоту об оплате"""

        deposit: DepositEntity = await self._uow.deposit_repo.acquire_deposit_by_id(
            deposit_id
        )
        deposit.update_status(DepositStatus.waiting_payment)
        deposit.update_invoice_path(invoice_filename)

        await self._uow.deposit_repo.update_deposit(deposit)

        await self._uow.commit()

        logger.info(f"Deposit {deposit_id} invoice screenshot path was updated")
